home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Magnum One
/
Magnum One (Mid-American Digital) (Disc Manufacturing).iso
/
d7
/
lib231.arc
/
SALT.DOC
< prev
next >
Wrap
Text File
|
1990-05-11
|
28KB
|
569 lines
SALT.DOC Copyright (C) 1990 Liberation Enterprises.
An introduction to Telix's script language.
This is not a comprehensive SALT tutor, and if you are seeking such you
won't find it here (a more extensive tutor will most likely be released
in the future). If you understand the logon scripts provided with
Telix, then you will probably be wasting your time reading this. This
document was designed for beginners, and simply explains some basics of
SALT, and some easy-to-use but useful functions. Everything is
explained in simple terms, to enable non-programmers or new Telix users
to write usable scripts. You will also be shown how to make use of the
dreaded SALT manual.
Learning SALT is usually the only major obstacle people run into with
Telix. As I'm sure you are aware, SALT is one of, if not *the* most
powerful 'script' language available for any communications program.
Unfortunately, extra power usually translates into a more involved
learning process--the more power (or features) you have, the more there
is to learn. However, you need not learn the entire language and study
the entire SALT manual to create useful scripts. There are a few SALT
statements and functions listed below, that will enable you to automate
fairly complex tasks, without getting into any major programming. The
functions are:
capture(); Open, close, or pause a capture file. Specify the name
of the capture file between double quotes (e.g.
capture("TELIX.CAP"). If you don't specify a path,
Telix creates the file in the same directory as
TELIX.EXE. See CAPCMD.SLT for example usage of
capture().
cputs(); Put a 'string' of text out the communications port
(cputs is 'c' for communications port (modem), 'put'
for... put, 's' for string. A string is just a bunch of
characters grouped together between double quotes; a
sentence (e.g. "This is a string").
delay_scr(); Pause the script from running for a certain amount of
time. This is similar to delay(), but it allows the
screen to be updated with incoming characters for the
duration of the delay. Delays can be used to wait for a
prompt, etc.
dos(); Gives you access to DOS from within a Telix script.
'Access to DOS' means you can carry out a simple DOS
command, such as COPY, DEL, etc., or you can even run
another program if necessary. The command must be
placed between double quotes. Examples:
dos("DEL TEST.FIL"); ...or... dos("123.EXE");
goto <label> A script or program normally runs from top to bottom, or
from the first statement to the last. To change this,
and skip immediately to another section of the script,
you use 'goto's.
hangup(); Breaks the connection by hanging up.
return(); End the current 'function' right where we are, and
return to the 'caller'. The 'caller' depends on where
the return() is found. If you return() from the main()
function that all scripts start at, then you return to
the calling script (The Liberator, etc.) or to Telix
The L i b e r a t o r v2.31 SALT.DOC - Page 2
terminal mode. The Liberator tests any value you
return() from your script's main() function.
waitfor(); Wait for some text to come in from the BBS, or until a
specified number of seconds elapses. Combined with
cputs(), this is a very useful function and can automate
many tasks.
Two other useful functions are:
send(); Send a file to the BBS (upload)
receive(); Receive a file from the BBS (download)
You can write many useful scripts using just these functions. However,
your scripts wouldn't be capable of making any intelligent decisions
using just the above... For example, waitfor() allows you to wait for a
specified number of seconds for a certain message or prompt to come in
from the BBS; but what if the message doesn't come in? You don't want
to answer a question if the question hasn't even been asked, so you
must have some way to test whether the text came in or not. This is
where these two statements come into play:
if() Tests whether something is TRUE (successful) or FALSE
(unsuccessful).
while() Does something 'while' a certain condition is TRUE.
What's all this about TRUE and FALSE? How do these things 'test'
whether something is successful (TRUE) or unsuccessful (FALSE)? There
is just a simple rule that they follow, which says that: "TRUE is
anything that is not zero". The number 1 is TRUE, since it is not
zero, the letter 'A' must be TRUE since it is not zero... 1 + 1 (one
plus one) is TRUE, since it's end result is not zero, etc. "FALSE is
anything that does end up to be zero"... 0 itself is FALSE, 1 - 1 (one
minus one) is FALSE since its end result is zero.
This doesn't have to make sense... (and it certainly didn't for me at
first) that's just the way it is. Anything that results in a zero
value is considered FALSE, anything that results in a non-zero value is
considered TRUE. If something is FALSE, it is also known as unsuccess-
ful, or 'not' successful. 'Not' is used in SALT to refer to something
that is not TRUE: if it's "not TRUE", it must be FALSE, or zero. I'm
attempting to burn this into your memory since it is used all over the
place in SALT and is important to pick up. The true/false rule makes
scripts 'smart' enough to carry out meaningful decisions. Almost
everything in SALT evaluates to TRUE or FALSE and can be tested with
if() and while(). Just using TRUE and FALSE was enough to create The
Liberator, and many of the other programs you use.
If I had some money, how much do I have? I have TRUE amount of money
(it must be TRUE since it isn't zero...). To test the value in SALT, I
could use:
if (money)
The L i b e r a t o r v2.31 SALT.DOC - Page 3
...which is the same as saying "if money is TRUE"... Of course, it
wouldn't do much good just to know this unless I was going to do
something with the information, like this:
if (money)
spend();
This is how if() operates. 'If' whatever is between the brackets ends
up to be TRUE (not zero), then the next statement (up to the first ;)
is carried out: spend(); in this case. Then we move happily along (by
the way, scripts execute from top to bottom, unless told otherwise).
If whatever is between if()'s brackets evaluates to FALSE ('money'
would be FALSE if it was equal to zero) then the statement immediately
following the if() is *skipped*. [Don't try to compile these ex-
amples... they're just nonsense used for demonstration. Some usable
examples are given later.]
if (this_is_TRUE)
then_do_this();
The next line following an if() or while() is normally indented to show
that it may not get executed if the result is FALSE, and depends on the
if(). [Note that the SALT compiler doesn't care whether you indent or
not... in fact you could place an entire SALT script all on one line an
it will compile just fine. Indending, and placing statements on
different lines is done solely for the benefit of people who read the
script. It makes scripts easier to follow and debug.]
Note also that the if() is not followed by a semicolon. This is
because if() executes the next statement UP TO the first semicolon. If
you use if(); then the semicolon is found immediately, and the if is
useless. The SALT script compiler (CS.EXE) gives a warning if you
specify if(); or while(); like this, with no statement to execute
before the semicolon.
While() works in the same way as if(), but instead of only executing
the next statement once, then moving along, it keeps running it over
and over again until whatever is between the brackets ends up to be
FALSE (or until we hit a 'break;' statement... which 'breaks' out of
while() 'loops'). Since it runs the next statement more than once,
while() is said to cause a 'loop' (you needn't remember this... it's
just a programming term). For example, just spend()ing ONCE is no fun
while() we still have some money left, so:
while (money) // while money is TRUE, or non-zero
spend(); // spend() some, then go back and check
// again in the while()
// once the while() is FALSE, (when money is equal to zero), then
// we exit the 'loop' and continue with any following statements
You could also reverse this by using the word 'not'. This would be an
appropriate while() loop to execute after the above spend()ing spree:
The L i b e r a t o r v2.31 SALT.DOC - Page 4
while (not money) // while money is 'not' TRUE (not TRUE is 0...FALSE)
work(); // go to work, then check again
Now, I suppose you're wondering where all this is leading to...
Believe it or not, if you understand the above it's only a matter of
time until you can write your own Liberator. There isn't much more to
The Liberator than 'if this, do that, else do this'... 'while this, do
that', etc. This is how all programs work. Everything must be
planned for and tested with statements like if() and while(). Since
computers basically have the intelligence of lightbulbs... making a
program appear 'smart' is a lot of work, and may require hundreds of
if/while's--each testing a different condition which you must an-
ticipate ahead of time. If you don't anticipate something, and if that
something happens, the computer will not automatically handle it for
you. Computers know absolutely nothing about what task is actually
going on, and basically shouldn't be considered as 'intelligent' any
more than your toaster would be (okay... they're a *little* smarter
than toasters, but not much).
What if you want to do two or more things if() something is TRUE (or
'not' TRUE)? This is what those curly brackets are for:
if (learning_SALT) // if learning_SALT is TRUE
{ // do whatever is between {}
read();
practice();
}
or more appropriately:
while (learning_SALT) // while learning_SALT is TRUE
{ // do whatever is between {}
read();
practice();
experiment();
}
// once learning_SALT is false, the script continues here
Now for some useful stuff to put between all these brackets. The
functions listed at the beginning of this document will replace the
dummy functions I demonstrated with in actual scripts. Don't panic,
but I want you to take a look in the SALT manual just for a second or
two. If you don't have the manual printed out, you can pretty well
forget learning anything useful in SALT, unless you have an incredible
memory, or are multitasking, etc. and can easily browse the manual on
disk while viewing your script... While programming any script, it is
essential to be able to quickly check the syntax (format) and 'return
values' of functions.
Look up waitfor() (all functions are listed alphabetically) and check
the 'Summary':
waitfor (str <waitstr>, int <timeout>);
The L i b e r a t o r v2.31 SALT.DOC - Page 5
This is not actually how you use the function. You don't type in 'str
<waitstr>', etc. These items are used as placeholders, to show you
what is expected, and where it is expected (commas always separate
arguments). 'str' refers to a 'string' (a bunch of letter, numbers,
symbols: a sentence) 'int' is an 'integer' (a number without a decimal
point: 1, -5, 10, 5000, etc). The angle brackets surround <descrip-
tions>, to give you some idea what the 'str' (string) or 'int'
(integer) is used for. Above, 'str <waitstr>' would be replaced with
the string (text) you want to wait for. Strings must be enclosed in
double quotes:
"This is a string of text that could replace str <waitstr>."
<timeout> would be replaced with the number of seconds you want to wait
before 'timing out' (giving up).
E.g. waitfor("First name?", 10); // wait 10 seconds for "First name?"
Also, check what waitfor() has to say under 'Return Value'. As you'll
see, it 'returns' TRUE if the string is found, and FALSE if it isn't
found... which makes it very convenient to test with an if() or
while(). Remember, if() and while() test the END RESULT of whatever is
between their brackets, and if you stick a function such as waitfor()
there, then the end result is the 'return value' of waitfor(). The
'return value' is always the end result of a function. Don't worry
about how it actually 'returns' this value, or even what a return value
is. For now, just accept that most functions have return values that
can be tested with if() or while():
if ( waitfor("First name?", 10) )
cputs("John Smith^M");
The above may look complex, but it's really not. The outer set of
brackets go with the if(), the inner go with the waitfor(). '^M' (two
characters, ^ and M) signifies Ctrl-M which is a Carriage Return or the
same as hitting <Return> or <Enter>. If any of your 'strings' don't
get <Enter>ed in your scripts, add ^M to the end of the string, before
the closing quote (").
Is this too easy? Now, what is stopping you from applying what you
know about waitfor(), and the SALT manual, to the other SALT functions
I pointed out at the beginning? Nothing at all... that's the whole
idea. If you understand the above, and understand what purpose looking
up a function in the SALT manual serves, then there really isn't much
more you need to know about SALT. It will only be a matter of time
until you memorize waitfor()... then cputs()... and so on until you can
create SALT scripts in your sleep. The only complicated part of
programming in SALT is trying to keep all the arguments straight (does
int <timeout> come first, or str <waitstr> in waitfor()... etc). This
is why I said it will be almost impossible to get anywhere in SALT
without instant access to the SALT manual. After over a year of
constant SALT programming, I still refer to the SALT manual frequently,
The L i b e r a t o r v2.31 SALT.DOC - Page 6
just to check what goes where, and what is returned.
EXAMPLES:
Many useful tasks can be carried out by simply waitingfor() a question
or message, and cputs()ing the reply or carrying out some other
function, such as receive()ing files, or opening a capture() file, etc.
You needn't use the track()/track_hit() functions, demonstrated in the
logon scripts, unless you absolutely have to track more than one prompt
at once.
Here's an example how to use waitfor() effectively:
main()
{
if (not waitfor("First name?", 10))
goto ERROR;
cputs("Your Name^M");
// this type of thing can handle many tasks. It means: 'if
// "First name?" DOESN'T come in within 10 seconds, jump down
// to the label ERROR below. Otherwise put the string "Your
// Name^M" out the comm. port' (send it to the BBS). Remember, 'not'
// means 'not TRUE' (FALSE), which is what waitfor() returns if
// <waitstr> is not found.
// ... Continue on here with the same type of thing for the next
// question or operation... You can handle just about anything
// with something like the above. Replace the cputs() with what-
// ever you want to do.
// ...
if (waitfor("Command?", 10)) // logon complete?
return; // end the script here to avoid ERROR:
ERROR: // labels used by 'goto's end with
// a colon (:)
hangup(); // hangup() the modem
}
I created the script below for use on a local BBS, using a few of the
functions outlined at the beginning. The script OPENs Mark Herring's
update door, hits a key at the end of each page while() the news is
being displayed, then selects and downloads my new copy of Deluxe (note
that you must be a registered Deluxe user to take advantage of the
update door, so please don't ask your Sysop for access if you are not a
registered Deluxe user). Once compiled, I put the scripts' name in
Custom Command 1 of a Liberator Command File (e.g. @SPUD-DL), and have
the whole process carried out automatically--The Liberator does the
dialing/logon/logoff, and SPUD-DL handles the download:
The L i b e r a t o r v2.31 SALT.DOC - Page 7
///////////////////////// SPUD-DL.SLT ///////////////////////////////
main()
{
cputs("OPEN 48^M"); // open door 48; replace w/proper door# for
// your BBS
// translation: put the string "OPEN 48<Enter>" out the comm.
// port (same as typing it manually online). Note the double quotes
// around OPEN 48^M, which must always surround strings.
if (not waitfor("Deluxe Update Door", 120))
return(0);
// translation: wait 120 seconds for the string "Deluxe
// Update Door" to come in from the BBS. If it doesn't come in,
// return() a 0 to 'the caller' (if called from a Custom Command,
// 'the caller' is The Liberator). You can break it down to
// three SALT functions: if(), waitfor(), and return(). A
// return() from main() always ends the script at that point.
while (waitfor("Press any key to continue...", 8))
cputs("^M");
// translation: wait 8 seconds for the string "Press any key to
// continue..." to come in, and 'while' the string keeps coming
// in, put an <Enter> (^M) out the communications port. This
// can also be broken down to three functions: while(),
// waitfor(), cputs(). When 8 seconds go by without receiving
// the string, waitfor() will return FALSE (zero), thus ending the
// while() loop and continuing below.
cputs("ALL^M"); // select ALL files for downloading (Door option)
delay_scr(20); // delay for 20/10th's of a second, or 2 seconds
cputs("DOWNLOAD^M"); // send the door command to start the download
if (waitfor("Begin your Zmodem download now...", 200))
receive('Z', "");
// if the prompt "Begin your Zmodem download now..." comes in
// within 200 seconds, then we start the download with the
// receive(). Otherwise we ignore the receive and continue
// below. See the SALT manual for send/receive protocol
// letters. Also note that the Zmodem protocol passes the
// filename (the BBS sends it with the file), so we don't have
// to specify it in the receive() function--hence the "" where
// the filename should be. Receive() continues below when the
// download completes...
waitfor("Command? ", 10); // pause for 10 seconds or until prompt
cputs("QUIT^M"); // then exit the door and...
waitfor("Command? ", 120);// waitfor PCBoard prompt to let The
// Liberator continue.
}
/////////////////////////////////////////////////////////////////
The L i b e r a t o r v2.31 SALT.DOC - Page 8
The script above is included with The Liberator, so you needn't type it
in if you have an update door on your BBS and want to make use of it.
Of course, you should change the door number in the "OPEN 48" to the
correct door on your BBS. Simply type OPEN manually at a PCBoard
prompt to view available doors and see if your BBS has a Deluxe update
door. You must have registered Mark Herring's Shareware reader, and
have a Deluxe serial number before making use of the door. If the door
doesn't let you in, leave a C)omment to your Sysop with your Deluxe
serial number.
I called the script SPUD-DL.SLT, for SParky (Mark Herring's nickname)
Update Door-DownLoad script. All scripts, as I'm sure you are aware,
must be compiled before use with the 'CS.EXE' (Compile Script) program.
Type 'CS SPUD-DL' to compile this one.
You can use the above techniques to automate just about any job
(waitfor a prompt, if not found 'goto' somewhere else, or 'return',
otherwise enter the response). I hope that if you are confused by any
of the above, that you'll take the time to review it and experiment
with some of the functions listed. Learning the above basics of SALT
will give you considerably more enjoyment from Telix.
Another Telix automator allows you to create scripts using something
like the above limited functions, but implements it so that the scripts
can only be interpreted by the automator itself and are useless to
Telix. The syntax of the functions is different (dropping a bracket
here, adding a colon there), but just as time-consuming as learning the
actual SALT functions, in my opinion. I think you're better off
spending your time gaining some control over SALT itself, so that you
are not dependant on The Liberator to run your scripts for you. This
gives you the chance to automate tasks on BBS's that The Liberator
doesn't support, plus gives you more use of Telix itelf.
For PCBoard BBS scripts though, you might as well plug the scripts you
create into a Custom Command and take advantage of The Liberator's
logon/logoff, dialing delay, Master, etc. Having The Liberator execute
other SALT scripts is very simple. See the section on Custom Commands
in LIBERATE.DOC for more information.
If you absolutely have to waitfor() more than one prompt at one time,
you must use the track()/track_hit() functions, which are demonstrated
in PCBOARD.SLT and other logon scripts. However, if possible start
with only the functions pointed out above, to avoid getting over-
whelmed. There are quite a few functions in SALT, and I still keep the
manual within arm's length to look up functions I don't use very
often. You truly won't get anywhere in SALT, without using the SALT
manual, unless you can somehow memorize the syntax/return values for
every function you use. Keep the manual handy for reference, now that
you know how to use it. Look up functions for reference when you need
them.
One thing I'd also like to demonstrate, is how to define your own
The L i b e r a t o r v2.31 SALT.DOC - Page 9
'functions' in SALT. It is almost so easy that it's not worth
explaining, since all you have to do is think up a name, and stick the
function in your script, just as you create the main() function. The
reason I want to demonstrate functions is to save you the inevitable
frustration of forgetting to put a ^M after your string, within
cputs(). To avoid having to specify ^M for each string, we simply
create a new cputs() function:
///////////////////// Start of script ///////////////////////////
main()
{
cputs_cr("Will <Enter> be sent after this string?");
}
cputs_cr(str string)
{
cputs(string);
cputs("^M"); // Yes, cputs_cr() never forgets the ^M...
}
////////////////////// End of script ////////////////////////////
The above is one script consisting of two separate functions: main()
and cputs_cr() (cputs with a CR or carriage return). You could call
cputs_cr() 'knurts()' if you wanted to... but normally we try to make
the name remind what the function does. Cputs_cr() accepts 1 str
(string) and chooses to call it 'string'. You could also call 'string'
anything you wanted to:
cputs_cr(str salt_is_easy)
{
cputs(salt_is_easy);
cputs("^M");
}
Once you stick cputs_cr() in any of your Telix scripts, you can then
use it just as you would cputs! If you wanted to pause the entry of
'string' for certain time before cputs()ing it, you could also pass a
delay to cputs_cr() like so:
main()
{
cputs_cr("This is a string", 5);
}
cputs_cr(str string, int delay_time)
{
delay_scr(delay_time); // delay_scr() pauses the script
cputs(string);
cputs("^M");
}
Using functions() can really cut down on your typing, and can make
scripts much easier to work with -- and more reliable.
The L i b e r a t o r v2.31 SALT.DOC - Page 10
Before coming to a close, there's also one other item, that while it
wasn't used in any of the scripts demonstrated here, it is used in the
logon scripts provided with Telix and can be fairly confusing to
beginners. What I'm referring to the equality test ==, or two equals
signs. Why use two instead of just one? Well, in SALT one equal sign
is used to actually ASSIGN a value to a specific item. If you wanted
to set the 'variable' stat to the number 10, you would use:
stat = 10;
To *test* whether stat was EQUAL TO the number 10, you use two equals
signs:
if (stat == 10)
prints("This is printed if stat is equal to 10");
If you used 'if (stat = 10)' then Telix would actually ASSIGN 10 to the
variable stat, then of course the if() would be TRUE since 10 is a TRUE
value (non zero). This is one to watch for in your scripts. Telix
doesn't give a warning if you use the wrong number of equals signs,
since you may have a good reason for one or two in any situation... it
assumes you know what you're doing. If something is getting carried
out when it shouldn't, first check for a semicolon following the if();
or while(); and if that's not the problem see if you inadvertanly used
the assigment operator (=) instead of the equality test (==).
That's it for now. I know you probably still have many questions, and
I hope to expand this tutor in the future... but I hope it was
informative and allows you to make some use of Telix SALT!